package com.zmn.plat.business.impl.product;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.plat.business.interfaces.product.ProductCache;
import com.zmn.plat.business.interfaces.servcategory.ShowCategoryAssociationBService;
import com.zmn.plat.common.constant.ProductConsts;
import com.zmn.plat.model.entity.category.ServCategAndCategTwoQuery;
import com.zmn.plat.model.entity.product.ProductQuery;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.ServProductRelation;
import com.zmn.plat.model.entity.product.ServProductRelationQuery;
import com.zmn.plat.model.entity.servcategory.ShowCategoryAssociationVO;
import com.zmn.plat.model.vo.product.ProductAllMsgVO;
import com.zmn.plat.services.interfaces.product.ServProductRelationService;
import com.zmn.plat.services.interfaces.product.ServProductService;

/**
 * @author : tanghongjun
 * @since 2018/7/12 16:15
 */
@Service
public class ProductCacheImpl implements ProductCache {

    private Logger logger = LoggerFactory.getLogger(ProductCacheImpl.class);

    @Resource
    ServProductService servProductService;

    @Resource
    ServProductRelationService servProductRelationService;

    @Resource
    ShowCategoryAssociationBService showCategoryAssociationBService;

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:allmsg:id'+#p0", unless = "#result == null")
    public ProductAllMsgVO findByKey(Integer productId) {
        return servProductService.findAllMsgByKey(productId);
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:allmsg:ids:'+#p0", unless = "#result == null")
    public List<ProductAllMsgVO> listByKeys(List<Integer> productIdList) {
        return servProductService.listAllMsgByKeys(productIdList);
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:allmsg:query:'+#p0", unless = "#result == null")
    public List<ProductAllMsgVO> listByProductQuery(ProductQuery productQuery) {
        return servProductService.listAllMsgByProductQuery(productQuery);
    }
    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:allmsg:query:'+#p0", unless = "#result == null")
    public List<ProductAllMsgVO> listProductByQuery(ProductQuery productQuery) {
        return servProductService.listProductByQuery(productQuery);
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:list:show:product:'+#p0+':status:'+#p1", unless = "#result == null")
    public List<ServProduct> listProductByShowProductIdAndStatus(Integer showProductId, Integer status) {
        if (NumberUtil.isNullOrZero(showProductId)) {
            logger.error("前台产品ID不能为空");
            return Collections.emptyList();
        }
        ServProductRelationQuery query = new ServProductRelationQuery();
        query.setShowProductId(showProductId);
        List<ServProductRelation> productRelationList = servProductRelationService.listByQuery(query);
        if (CollectionUtils.isEmpty(productRelationList)) {
            logger.error("当前前台产品ID没有关联的后台产品");
            return Collections.emptyList();
        }
        List<Integer> productIds = productRelationList.stream().map(ServProductRelation::getProductId).collect(Collectors.toList());
        List<ServProduct> servProductList = servProductService.listByIdList(productIds, status);

        return servProductList;
    }

    @Override
    @Cacheable(cacheNames = "redis5m", key = "'product:serv:query:type:'+#p0+':productId:'+#p1+':serv:'+#p2+':categTwo:'+#p2", unless = "#result == null")
    public List<ServCategAndCategTwoQuery> listServCategAndCategTwoQueryByTypeAndProductIdOrCategId(Integer type, Integer productId, Integer servCategId, Integer categTwoId) {
        List<ServCategAndCategTwoQuery> servCategAndCategTwoQueryList = new ArrayList<>();

        // 如果参数为后端产品ID，直接查询产品相关信息
        if (Objects.equals(type, ProductConsts.ERP_PRODUCT_TYPE) && Objects.nonNull(productId)) {
            ServProduct servProduct = servProductService.findByKey(productId);
            if (Objects.isNull(servProduct) || Objects.equals(servProduct.getStatus(), GlobalConsts.NO)) {
                logger.error("当前产品不存在或已禁用");
                return Collections.emptyList();
            }
            ServCategAndCategTwoQuery servCategAndCategTwoQuery = new ServCategAndCategTwoQuery(servProduct.getServCategId(),servProduct.getCategOneId(), servProduct.getCategId());
            servCategAndCategTwoQueryList.add(servCategAndCategTwoQuery);
        }

        // 如果参数为前端产品ID，根据产品ID获取对应的后端产品ID，并且获取后端产品ID的服务分类和二级产品分类
        if (Objects.equals(type, ProductConsts.EC_PRODUCT_TYPE) && Objects.nonNull(productId)) {
            List<ServProduct> servProductList = listProductByShowProductIdAndStatus(productId, GlobalConsts.YES);
            List<ServCategAndCategTwoQuery> servCategAndCategTwoQuerys =
                servProductList.stream().map(servProduct -> new ServCategAndCategTwoQuery(servProduct.getServCategId(),servProduct.getCategOneId(), servProduct.getCategId())).distinct().collect(Collectors.toList());
            servCategAndCategTwoQueryList.addAll(servCategAndCategTwoQuerys);
        }

        // 如果参数为后端产品分类ID，直接组装返回值
        if (Objects.equals(type, ProductConsts.ERP_PRODUCT_TYPE) && Objects.nonNull(servCategId) && Objects.nonNull(categTwoId)) {
            servCategAndCategTwoQueryList.add(new ServCategAndCategTwoQuery(servCategId,null, categTwoId));
        }

        // 如果参数为前端产品分类ID，查询对应后端产品分类ID
        if (Objects.equals(type, ProductConsts.ERP_PRODUCT_TYPE) && Objects.nonNull(servCategId) && Objects.nonNull(categTwoId)) {
            List<ShowCategoryAssociationVO> voList = showCategoryAssociationBService.listByShowCategoryId(servCategId, null, categTwoId);
            List<ServCategAndCategTwoQuery> servCategAndCategTwoQuerys = voList.stream()
                .map(showCategoryAssociationVO -> new ServCategAndCategTwoQuery(showCategoryAssociationVO.getServCategId(),showCategoryAssociationVO.getCategOneId(), showCategoryAssociationVO.getCategId())).distinct().collect(Collectors.toList());
            servCategAndCategTwoQueryList.addAll(servCategAndCategTwoQuerys);
        }

        return servCategAndCategTwoQueryList;
    }
}
